<!--
/**
* @description 用户管理
* @author mdong
* @date 2020-05-11
*/
-->
<template>
  <div class="userManagement">
    <section class="userManagement-tree">
      <!-- 左侧树状图 -->
      <div class="tree-content">
        <a-tree :show-line="showLine"
                :show-icon="true"
                :tree-data="treeData"
                :replace-fields="replaceFields"
                @select="onSelect">
          <template slot="custom-folder" slot-scope="{ expanded }">
            <a-icon :type="expanded ? 'folder-open' : 'folder'" theme="filled"/>
          </template>
        </a-tree>
      </div>
    </section>
    <div class="index-right-box">
      <!-- 右侧查询 -->
      <a-form-model ref="searchForm"
                    class="index-search-form-model"
                    :model="searchForm"
                    layout="inline"
      >
        <a-form-model-item label="用户名称"
                           prop="name">
          <a-input v-model="searchForm.name"
                   allowClear
                   placeholder="请输入用户名称">
          </a-input>
        </a-form-model-item>
        <a-form-model-item label="手机号码"
                           prop="phone">
          <a-input v-model="searchForm.phone"
                   allowClear
                   placeholder="请输入手机号码">
          </a-input>
        </a-form-model-item>
        <a-form-model-item label="用户状态"
                           prop="state">
          <a-select v-model="searchForm.state"
                    allowClear
                    placeholder="请选择用户状态">
            <a-select-option v-for="(item,index) in stateConst "
                             :key="index"
                             :value="item.value"> {{item.name}}</a-select-option>
          </a-select>
        </a-form-model-item>
        <a-form-model-item label="创建时间">
          <a-range-picker v-model="createTime"
                          allowClear></a-range-picker>
        </a-form-model-item>
        <a-form-model-item class="top-widget-btn">
          <a-button type="primary"
                    icon="search"
                    shape="round"
                    @click="queryListBycondition">查询</a-button>
          <a-button icon="retweet"
                    shape="round"
                    @click="resetList">重置</a-button>
        </a-form-model-item>
      </a-form-model>
      <!-- 顶部控件 -->
      <section class="table-list">
        <!-- 操作按钮 -->
        <div class="table-opt-btns">
          <a-button type="primary"
                    icon="plus"
                    :disabled="!currSelTreeNode.id"
                    @click="addUser">新增</a-button>
          <a-button :disabled="!isSelecte"
                    icon="delete"
                    @click="batchRemove">批量删除</a-button>
        </div>
        <!-- 表格操作 -->
        <a-table :columns="columns"
                 :dataSource="tableData"
                 bordered
                 :customRow="tableCustomRow"
                 rowKey="id"
                 @change="tableChange"
                 :rowSelection="{selectedRowKeys: selectedRowKeys,onChange: selectedRowChange}"
                 :loading="tableLoading"
                 :scroll="{ x: 1130 }"
                 :pagination="pagination">
          <!-- 用户状态 0 正常 1 停用 -->
          <div slot="state"
               slot-scope="text,record,index"
               class="tabe-switch">
              <a-popconfirm title="确定要切换状态吗?"
                          @confirm="changeState(text, record, index)"
                          okText="是"
                          cancelText="否">
                <a-switch v-if="stateConst.length"
                          :checked="(stateConst.length && record.state === Number(stateConst[0].value)) || false"
                          :checked-children="stateConst.length && stateConst[0].name"
                          :un-checked-children="stateConst.length && stateConst[1].name"
                />
              </a-popconfirm>
          </div>
          <span slot="customOrgName"
               slot-scope="text,record"
          >
            {{getAreaName(treeData, record.orgId)}}
          </span>
          <div slot="operation"
               slot-scope="text,record,index"
               class="tabe-button">
            <a-button size="small"
                      type="primary"
                      icon="edit"
                      @click="editData(text, record, index)">编辑</a-button>
            <!--  <a-button size="small"
                      type="danger"
                      @click="resetPassword(text, record, index)">重置密码</a-button> -->
            <a-button size="small"
                      type="danger"
                      icon="user"
                      :disabled="currUserInfo.id === record.id"
                      @click="authorizeData(text, record, index)">授权</a-button>
            <a-button size="small"
                      type="danger"
                      icon="close"
                      :disabled="currUserInfo.id === record.id"
                      @click="delData(text, record, index)">删除</a-button>
          </div>
        </a-table>
        <!-- 表格 -->
        <!-- 新增编辑表格 -->
        <operate-form :operateVisible="operateVisible"
                      :currSelTreeNode="currSelTreeNode"
                      :optType="optType"
                      :getAreaName="getAreaName"
                      :treeData="treeData"
                      :confirm-loading.sync="confirmOptFormLoading"
                      :operateData="operateData"
                      @handleSubmit="submitUser"
                      @handleVisible="handleOperateTableVisible"></operate-form>
        <!-- 新增编辑表格 -->
        <a-modal title="角色选择"
                 :width="860"
                 :visible="transferVisible"
                 :confirm-loading="confirmLoading"
                 @ok="submitAuthorize"
                 okText="提交"
                 :okButtonProps="{props:{icon:'save'}}"
                 :cancelButtonProps="{props:{icon:'close-circle'}}"
                 @cancel="cancleAuthorize"
                 :destroyOnClose="true">
          <a-transfer :data-source="transferData.dataOfAuth"
                      show-search
                      :titles="['未拥有角色', '拥有角色']"
                      :operations="['授权', '移除']"
                      :filter-option="filterOption"
                      :target-keys="targetKeys"
                      :render="item => item.title"
                      :list-style="{
                        width: '350px',
                        height: '400px',
                      }"
                      @change="handleChange"
                      @search="handleSearch" />
        </a-modal>
      </section>
    </div>
  </div>
</template>
<script>
import { getDictData } from '@/request/api/common'
import { getPageHnRole } from '@/request/api/permissionManagement/roleManagement'
import { getPageUser, delUser, deleteUserBatch, addUser, getCurrentRole, authorize, pwaReset, updateUser } from '@/request/api/permissionManagement/user/user'
import { UserColumns } from '@/utils/columns'
import { getFinalPageNo, getCustomIconTreeData } from '@/utils/index'
import { FormModel, Switch, Modal, Select, Transfer, Tree, Input, DatePicker, Button, Table, Icon, Popconfirm } from 'ant-design-vue'
import { queryOrgTree } from '@/request/api/permissionManagement/org'
import OperateForm from './components/OperateForm'
export default {
  name: 'userManagement',
  components: {
    AFormModel: FormModel,
    AFormModelItem: FormModel.Item,
    ASwitch: Switch,
    ATransfer: Transfer,
    AModal: Modal,
    ATree: Tree,
    AInput: Input,
    AButton: Button,
    ATable: Table,
    OperateForm: OperateForm,
    ARangePicker: DatePicker.RangePicker,
    ASelect: Select,
    ASelectOption: Select.Option,
    AIcon: Icon,
    APopconfirm: Popconfirm
  },
  data () {
    return {
      // 授权的id
      opreateId: null,
      transferData: {
        loading: false,
        saving: false,
        // element拿到的原始数组
        dataOfAuth: [],
        // 右侧数据的索引
        keyOfAuth: [],
        // 加载页面时的原始左侧数据
        orgDataLeft: [],
        // 加载页面时的原始右侧数据
        orgDataRight: [],
        // 确认前左侧的数据项
        nowDataLeft: [],
        // 确认前右侧的数据项
        nowDataRight: [],
        // 左侧新增的数据
        diffDataLeft: [],
        // 右侧新增的数据
        diffDataRight: [],
        // 左侧新增提示数据
        msgAuth: [],
        // 右侧提示新增数据
        msgDel: [],
        // 当前正在编辑的用户uid
        editingUserId: ''
      },
      transferVisible: false,
      confirmLoading: false,
      mockData: [],
      stateConst: [],
      targetKeys: [],
      orgId: null,
      treeData: [],
      replaceFields: {
        children: 'childrenList',
        title: 'name',
        key: 'id'
      },
      showLine: true,
      showIcon: false,
      expandedKeys: ['0-0', '0-0-0', '0-0-0-0'],
      formLayout: 'horizontal',
      searchForm: {
        name: '',
        state: undefined
      },
      createTime: [],
      // 角色表头
      columns: UserColumns,
      // 表数据
      tableData: [],
      // 选中的id
      selectedKeys: [],
      // 表格选中数据
      selectedRowKeys: [],
      selections: [
        {
          title: '登录账号',
          align: 'center',
          ellipsis: true,
          dataIndex: 'username'
        }
      ],
      // 表格loading
      tableLoading: false,
      // 分页配置
      pagination: {
        current: 1, // 当前页数
        pageSize: 10, // 每页显示数量
        showQuickJumper: true, // 跳转
        showSizeChanger: true, // 显示改变每页数量
        total: 0, // 总数
        pageSizeOptions: ['10', '15', '20', '25'],
        showTotal: total => `共 ${total} 条` // 显示总数
      },
      // 是否打开新增和编辑抽屉
      operateVisible: false,
      // 新增编辑
      optType: 'add',
      // 新增和编辑抽屉数据
      operateData: {
        username: '',
        phone: '',
        orgId: '',
        roleName: '',
        parentName: '',
        name: '',
        state: '',
        orgIds: []
      },
      // 表单提交按钮loading
      confirmOptFormLoading: false,
      // 当前点击树节点
      currSelTreeNode: {},
      // 当前登录用户信息
      currUserInfo: {}
    }
  },
  watch: {
    'pagination.current': {
      handler: function (current) {
        this.selectedRowKeys = []
        this.selectedKeys = ''
      }
    }
  },
  computed: {
    // 是否有选中项
    isSelecte () {
      return this.selectedRowKeys.length > 0
    }
  },
  created () {
    this.getOrgTree()
    this.queryListByPage()
    this.getDictDataList()
  },
  mounted () {
    this.currUserInfo = JSON.parse(localStorage.getItem('ycloud-operate-user_info'))
  },
  methods: {
    // table自定义事件
    tableCustomRow (record) {
      return {
        on: { // 事件
          dblclick: (event) => {
            this.operateData = Object.assign({}, {
              id: record.id,
              parentName: this.getAreaName(this.treeData, record.orgId),
              orgIds: []
            })
            this.optType = 'view'
            this.operateVisible = true
          }
        }
      }
    },
    // 获取区域名
    getAreaName (treeData, idValue, idKey = 'id') {
      const ids = idValue.split(',')
      ids.pop()
      idValue = ids.pop()
      const listData = []
      function fnc (tree) {
        tree.forEach((p) => {
          listData.push(p)
          if (p.childrenList && (p.childrenList.length > 0)) {
            fnc(p.childrenList)
          }
        })
      }
      fnc(treeData)
      const target = listData.find((item) => item[idKey] === idValue)
      if (target) {
        return target.name
      } else {
        return '暂无'
      }
    },
    // 获取数据字典
    getDictDataList () {
      const params = 'Y-002'
      getDictData(params).then((res) => {
        if (res.code === '0') {
          const data = res.data
          this.stateConst = data['Y-002']
        }
      })
    },
    // 查询左侧树形结构数据
    getOrgTree () {
      const params = {}
      queryOrgTree(params).then((res) => {
        if (res.code === '0') {
          this.treeData = getCustomIconTreeData(res.data, 'childrenList')
        }
      })
    },
    // 查询列表数据
    queryDataByPage (query) {
      if (this.currSelTreeNode.id) {
        query = {
          orgId: this.currSelTreeNode.parentIds,
          ...query
        }
      }
      this.tableLoading = true
      if (this.createTime.length !== 0) {
        query.createStartTime = this.$moment(this.createTime[0]).format('YYYY-MM-DD ') + '00:00:00'
        query.createEndTime = this.$moment(this.createTime[1]).format('YYYY-MM-DD ') + '23:59:59'
      }
      const params = {
        pageNum: this.pagination.current,
        pageSize: this.pagination.pageSize,
        param: query
      }
      getPageUser(params).then((res) => {
        this.tableLoading = false
        if (res.code === '0') {
          this.tableData = res.data.list
          this.pagination.total = res.data.total
        } else {
          this.tableDdata = []
          this.pagination.total = 0
        }
      }).catch(error => {
        this.tableLoading = false
        console.log(error)
      })
    },
    // 默认查询
    queryListByPage () {
      const params = {}
      this.queryDataByPage(params)
    },
    // 表格变动分页查询
    tableChange (pagination, filters, sorter) {
      this.pagination = pagination
      this.queryDataByPage(this.searchForm)
      // 查询接口
    },
    // 重置
    resetList () {
      this.pagination.current = 1
      this.createTime = []
      this.$refs.searchForm.resetFields()
      this.queryListByPage()
    },
    // 条件查询
    queryListBycondition () {
      this.pagination.current = 1
      this.queryDataByPage(this.searchForm)
    },
    // 授权穿梭框的配置
    filterOption (inputValue, option) {
      return option.title.indexOf(inputValue) > -1
    },
    // 改变穿梭框数据
    handleChange (targetKeys, direction, moveKeys) {
      this.targetKeys = targetKeys
    },
    // 选中行
    selectedRowChange (selectedRowKeys, selectedRows) {
      this.selectedRowKeys = selectedRowKeys
      const selectedKeys = []
      selectedRows.forEach((item) => {
        selectedKeys.push(item.id)
      })
      this.selectedKeys = selectedKeys.length === 1 ? selectedKeys[0] : selectedKeys.join(',')
    },
    // 批量删除
    batchRemove () {
      this.$confirm({
        title: '你确定要删除选中数据?',
        okText: '是',
        okType: 'danger',
        cancelText: '否',
        onOk: () => {
          deleteUserBatch({ id: this.selectedKeys }).then((res) => {
            if (res.code === '0') {
              this.$message.success('删除成功!')
              this.pagination.current = getFinalPageNo(
                this.pagination.total,
                this.pagination.current,
                this.pagination.pageSize,
                this.selectedRowKeys.length)
              this.selectedRowKeys = []
              this.selectedKeys = ''
              this.queryListByPage()
            }
          }).catch(() => {
          })
        }
      })
    },
    handleSearch (dir, value) {
    },
    // 点击树状图
    onSelect (selectedKeys, info) {
      this.pagination.current = 1
      if (!selectedKeys.length) {
        this.currSelTreeNode = {}
        this.queryDataByPage(this.searchForm)
        return
      }
      this.currSelTreeNode = info.selectedNodes[0].data.props
      this.orgId = selectedKeys
      this.operateData.parentName = info.node.title
      this.queryDataByPage(this.searchForm)
    },
    // 提交新增或编辑
    async submitUser (params) {
      this.confirmOptFormLoading = true
      delete params.parentName
      if (this.optType === 'add') {
        const query = Object.assign({}, params)
        await addUser(query).then((res) => {
          if (res.code === '0') {
            this.$message.success('新增成功!')
            this.operateVisible = false
            this.resetList()
          }
        })
      } else {
        const query = Object.assign({}, params, {
          id: this.operateData.id
        })
        await updateUser(query).then((res) => {
          if (res.code === '0') {
            this.$message.success('编辑成功!')
            this.operateVisible = false
            this.queryDataByPage(this.searchForm)
          } else {
            this.operateVisible = true
          }
          for (const key in this.operateData) {
            this.operateData[key] = ''
          }
        })
      }
      this.confirmOptFormLoading = false
    },
    // 关闭新增和编辑抽屉
    handleOperateTableVisible (parms) {
      this.operateVisible = parms
    },
    // 新增角色
    addUser () {
      if (!this.orgId) {
        this.$message.error('请先选择组织！')
        return false
      } else {
        this.operateVisible = true
        this.optType = 'add'
        this.operateData.username = ''
        this.operateData.phone = ''
        this.operateData.createUser = ''
        this.operateData.roleName = ''
        this.operateData.orgId = this.currSelTreeNode.parentIds
        this.operateData.name = ''
        this.operateData.state = ''
        this.operateData.parentName = this.currSelTreeNode.title
        this.operateData.orgIds = []
      }
    },
    // 编辑数据
    editData (text, record, index) {
      this.operateData = Object.assign({}, {
        id: record.id,
        parentName: this.getAreaName(this.treeData, record.orgId),
        orgIds: []
      })
      this.optType = 'edit'
      this.operateVisible = true
    },
    // 切换状态
    changeState (text, record, index) {
      const query = Object.assign({}, record)
      if (record.state === 1) {
        query.state = 2
      } else {
        query.state = 1
      }
      updateUser(query).then((res) => {
        if (res.code === '0') {
          this.$message.success('设置成功!')
          this.queryDataByPage(this.searchForm)
        }
      })
    },
    // 重置密码
    resetPassword (text, record, index) {
      this.$confirm({
        title: '确定要重置密码吗?',
        okText: '是',
        okType: 'danger',
        cancelText: '否',
        onOk: () => {
          const params = {
            userId: record.id
          }
          pwaReset(params).then((res) => {
            if (res.code === '0') {
              this.$message.success('重置成功!')
              this.queryDataByPage(this.searchForm)
            }
          }).catch(() => {
          })
        }
      })
    },
    // 删除数据
    delData (text, record, index) {
      this.$confirm({
        title: '删除之后无法恢复，确定要删除数据吗?',
        okText: '是',
        okType: 'danger',
        cancelText: '否',
        onOk: () => {
          delUser({ id: record.id }).then((res) => {
            if (res.code === '0') {
              this.$message.success('删除成功!')
              this.pagination.current = getFinalPageNo(
                this.pagination.total,
                this.pagination.current,
                this.pagination.pageSize,
                1)
              this.queryListByPage()
              // 从批量删除数组中 去掉当前删除的数据
              if (this.selectedRowKeys.includes(record.id)) {
                const index = this.selectedRowKeys.findIndex((id) => id === record.id)
                this.selectedRowKeys.splice(index, 1)
                this.selectedKeys = this.selectedKeys.join(',')
              }
            }
          })
        }
      })
    },
    // 打开授权弹窗
    authorizeData (text, record, index) {
      const params = { id: record.id }
      this.opreateId = record.id
      const query = { pageNum: 1, pageSize: 9999, param: { status: '1' } }
      this.getRoleData(query, params)
      //
    },
    // 获取已有角色和所有角色
    getRoleData (data, params) {
      this.transferData.dataOfAuth = []
      this.transferData.orgDataLeft = []
      this.transferData.orgDataRight = []
      this.targetKeys = []
      Promise.all([getPageHnRole({
        ...data
      }), getCurrentRole(params)])
        .then(res => {
          if (res[0] && res[1]) {
            const allRole = res[0].data.list
            if (allRole) {
              allRole.forEach(v => {
                this.transferData.dataOfAuth.push({ key: v.id, title: v.name })
              })
            }
            const existRole = res[1].data
            if (existRole && existRole.length) {
              // 注意此处经过了单点域筛选要经过两重循环筛选,2是用户拥有的所有角色,2中用id过滤出存在于1中的,界面数据才正确
              existRole.forEach(v => {
                allRole.forEach(m => {
                  if (v.id === m.id) {
                    this.targetKeys.push(v.id)
                  }
                })
              })
            }
          }
          // 右侧数据
          this.targetKeys.forEach(m => {
            this.transferData.orgDataRight.push(
              this.transferData.dataOfAuth.find(val => {
                return val.key === m
              })
            )
          })
          // 左侧数据
          this.transferData.orgDataLeft = this.transferData.dataOfAuth
            .concat(this.transferData.orgDataRight)
            .filter(
              v =>
                !this.transferData.dataOfAuth.includes(v) ||
                !this.transferData.orgDataRight.includes(v)
            )
          this.transferVisible = true
        })
        .catch(error => {
          console.log(error)
        })
    },
    // 提交授权
    async submitAuthorize () {
      this.confirmLoading = true
      // 强制设置默认值
      // 清空取消前的msg数据
      this.transferData.nowDataLeft = []
      this.transferData.nowDataRight = []
      // 对比增删的数据
      this.targetKeys.forEach(m => {
        this.transferData.nowDataRight.push(
          this.transferData.dataOfAuth.find(val => {
            return val.key === m
          })
        )
      })
      this.transferData.nowDataLeft = this.transferData.dataOfAuth
        .concat(this.transferData.nowDataRight)
        .filter(
          v =>
            !this.transferData.dataOfAuth.includes(v) ||
            !this.transferData.nowDataRight.includes(v)
        )
      // 增加的权限
      this.transferData.diffDataLeft = this.transferData.orgDataRight.filter(v =>
        this.transferData.nowDataLeft.includes(v)
      )
      // 删除的权限
      this.transferData.diffDataRight = this.transferData.orgDataLeft.filter(v =>
        this.transferData.nowDataRight.includes(v)
      )
      if (
        !this.transferData.diffDataLeft.length &&
        !this.transferData.diffDataRight.length
      ) {
        this.$message.info('此次授权操作未增删角色')
        return
      } else {
        this.$message.info(`授权了${this.transferData.diffDataRight.length}个角色，删除了${this.transferData.diffDataLeft.length}个角色`)
      }
      // this.transferData.saving = false
      const roleIdList = []
      if (this.transferData.diffDataRight.length > 1) {
        this.transferData.diffDataRight.forEach((item) => {
          roleIdList.push(item.key)
        })
      }
      const params = {
        id: this.opreateId,
        roleIdList: this.targetKeys
      }
      await authorize(params).then((res) => {
        if (res.code === '0') {
          this.$message.success('操作成功')
        }
      })
      this.confirmLoading = false
      this.transferVisible = false
    },
    // 取消权限
    cancleAuthorize () {
      this.transferVisible = false
    }
  }
}
</script>
<style lang="scss">
.userManagement {
  width: 100%;
  height: 100%;
  display: flex;
  .userManagement-tree {
    min-width: 256px;
    background-color: #ffffff;
    margin-right: 20px;
    padding: 20px;
    box-sizing: border-box;
    .tree-content {
      height: 100%;
      overflow-y: auto;
    }
  }
  .table-list {
    background-color: #ffffff;
    padding: 20px;
    box-sizing: border-box;
    overflow-y: auto;
  }
}
</style>
